package org.nlp2rdf.navigator.client.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.nlp2rdf.navigator.client.common.ConceptDTO;
import org.nlp2rdf.navigator.client.common.LearnedConceptDTO;
import org.nlp2rdf.navigator.client.common.StoredConceptDTO;
import org.nlp2rdf.navigator.client.functionality.Tooltip;

import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Some Actions to use on LearningResultDTO
 * 
 * @author Sebastian Hellmann <hellmann@informatik.uni-leipzig.de>
 * 
 */
public class ConceptDTOHelper {

	public static final Map<String, String> colorsForMOSKeyWords = getMap();
	public static final Set<String> MOSKeywords = colorsForMOSKeyWords.keySet();
	
	

	private static Map<String, String> getMap() {
		Map<String, String> colors = new HashMap<String, String>();
		colors.put("that", "Tomato");
		colors.put("some", "Tomato");
		colors.put("and", "SlateBlue");
		colors.put("or", "SlateBlue");
		colors.put("value", "FireBrick");
		colors.put("only", null);
		colors.put("someonly", null);
		return colors;
	}

	public static FlowPanel getHTMLAsFlowPanel(ConceptDTO learningResult) {

		List<HTML> tmp = new ArrayList<HTML>();
		List<String> tokenized = tokenize(learningResult.getManchesterSyntaxString());

		String sn = "concept-labels";

		for (String token : tokenized) {
			if (token.equals("(") || token.equals(")")) {
				tmp.add(setStyleName(new HTML(token), sn));
				// named construct
			} else if (learningResult.getNamedConceptsAndProperties().contains(token)) {

				String nice = stripNamespace(token, learningResult.getBase(), learningResult
						.getNamespaceToPrefix());
				HTML h = setStyleName(new HTML(), sn);
				h.setHTML((span("style='font-style:italic;'", nice)));

				Tooltip.assignToolTip(h, getToolTipForNamedConcept(learningResult, token));
				tmp.add(h);
			} else if (MOSKeywords.contains(token) && colorsForMOSKeyWords.get(token) != null) {
				HTML h = setStyleName(new HTML(), sn);
				h.setHTML(span("style='color:" + colorsForMOSKeyWords.get(token) + "'", token));
				tmp.add(h);
			} else {
				HTML h = setStyleName(new HTML(), sn);
				h.setHTML(span("", token));
				tmp.add(h);
			}

		}
		// assemble again

		FlowPanel ret = new FlowPanel();
		for (HTML l : tmp) {
			l.setHTML(l.getHTML() + "&nbsp;");
			ret.add(l);
		}

		return ret;
	}

	private static VerticalPanel getToolTipForNamedConcept(ConceptDTO concept, String token) {
		VerticalPanel f = new VerticalPanel();
		f.add(new Label(token));
		String comment;
		if (concept instanceof LearnedConceptDTO) {
			LearnedConceptDTO l = (LearnedConceptDTO) concept;
			comment = l.getConceptComments().get(token);
		} else {
			comment = concept.getComment();
		}
		f.add(new Label(((comment == null) ? "No comment available" : comment)));

		return f;
	}

	public static VerticalPanel getInfoTooltip(ConceptDTO concept) {
		VerticalPanel f = new VerticalPanel();
		f.add(new Label(concept.getLabel()));
		f.add(new Label(concept.getComment()));
		f.add(new Label(concept.getManchesterSyntaxString()));
		if (concept instanceof LearnedConceptDTO) {
			LearnedConceptDTO l = (LearnedConceptDTO) concept;
			f.add(new Label("Acc: " + l.getAccuracy()));

			if (l instanceof StoredConceptDTO) {
				StoredConceptDTO st = (StoredConceptDTO) l;
				f.add(new Label("Concept is stored"));
				f.add(new Label("Nr of views: " + st.getHitcounter()));
			}
		}
		return f;
	}

	public static VerticalPanel getDebugToolTip(ConceptDTO concept) {
		VerticalPanel f = new VerticalPanel();
		f.add(getInfoTooltip(concept));
		f.add(new Label(concept.getClass()+""));
		f.add(new Label("KBSyntax:" + concept.getKbSyntaxString()));
		f.add(new Label("named:" + concept.getNamedConceptsAndProperties()));
		f.add(new Label("base:" + concept.getBase()));
		f.add(new Label("NtoP:" + concept.getNamespaceToPrefix()));
		f.add(new Label("PtoN:" + concept.getPrefixToNamespace()));

		if (concept instanceof LearnedConceptDTO) {
			LearnedConceptDTO l = (LearnedConceptDTO) concept;
			f.add(new Label("Comments:" + l.getConceptComments()));
			f.add(new Label("Examples:" + l.getExamples()));

			if (l instanceof StoredConceptDTO) {
				StoredConceptDTO st = (StoredConceptDTO) l;
				f.add(new Label("Concept is stored"));
				f.add(new Label("Nr of views: " + st.getHitcounter()));
			}
		}
		return f;
	}

	public static void add(String a, String b, FlexTable f) {
		int rows = f.getRowCount();
		f.setWidget(rows, 0, new Label(a + ""));
		f.setWidget(rows, 1, new Label(b + ""));
	}

	private static <T extends Label> T setStyleName(T l, String style) {
		l.setStyleName(style);
		return l;
	}

	public static String getMOSNoHTML(ConceptDTO concept) {
		StringBuffer nohtmlDescription = new StringBuffer();

		List<String> tokenized = tokenize(concept.getManchesterSyntaxString());
		for (String token : tokenized) {
			String current = token;
			if (current.contains(")")) {
				nohtmlDescription.append(current + " ");
			} else if (current.contains("(")) {
				nohtmlDescription.append(current);
				// named construct
			} else if (concept.getNamedConceptsAndProperties().contains(current)) {
				nohtmlDescription.append(stripNamespace(current, concept.getBase(), concept
						.getNamespaceToPrefix())
						+ " ");
			} else {
				nohtmlDescription.append(current + " ");
			}

		}
		return nohtmlDescription.toString();
	}

	public static Set<String> extractNamedConceptsAndProperties(ConceptDTO learningResultDTO) {
		Set<String> namedConcepts = new HashSet<String>();
		String[] ar = learningResultDTO.getManchesterSyntaxString().split(" ");
		for (String string : ar) {
			String currentString = string.trim().replaceAll("\\(", "").replaceAll("\\)", "");
			if (MOSKeywords.contains(currentString.toLowerCase())) {
				continue;
			} else {
				namedConcepts.add(currentString);
			}
		}
		return namedConcepts;
	}

	/**
	 * splits first by " " and then before and after each "(", ")"
	 * 
	 * @param manchesterOWLSyntax
	 * @return
	 */
	private static List<String> tokenize(String manchesterOWLSyntax) {
		manchesterOWLSyntax = manchesterOWLSyntax.replaceAll("\\s+", " ");
		String[] conceptSplits = manchesterOWLSyntax.split(" ");

		List<String> ret = new ArrayList<String>();

		for (String string : conceptSplits) {
			String current = string;

			String before = "";
			while (current.startsWith("(")) {
				before += "(";
				current = current.substring(1);
			}

			String after = "";
			while (current.endsWith(")")) {
				after += (")");
				current = current.substring(0, current.length() - 1);
			}
			if (!before.isEmpty()) {
				ret.add(before);
			}
			if (!current.isEmpty()) {
				ret.add(current);
			}
			if (!after.isEmpty()) {
				ret.add(after);
			}

		}
		return ret;
	}

	public static void main(String[] args) {
		String c = "(http://www.opengis.net/gml/_Feature and dbp:sovereigntyType some  Thing)";
		System.out.println(tokenize(c));
	}

	public static String stripNamespace(String uri, String base, Map<String, String> nameSpaceToPrefix) {
		String name = uri.replace(base, "");
		for (String s : nameSpaceToPrefix.keySet()) {
			name = name.replace(s, nameSpaceToPrefix.get(s) + ":");
		}
		return name;
	}

	public static String span(String attribute, String child) {
		return "<span " + attribute + " >" + child + "</span> ";
	}
}
